﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
using System.Xml.Linq;

namespace QRCodeTool
{
    public partial class FrmMain : Form
    {
        /// <summary>
        /// 打印机的通讯端口
        /// 波特率为 9600
        /// </summary>
        SerialPort printPort = new SerialPort();
        string printPortNameKey = "printPortName";
        string printPortName = "";
        /// <summary>
        /// 读设备线程
        /// </summary>
        Thread readDevThread = null;
        bool readDevRun = false;
        /// <summary>
        /// 设备的通讯端口
        /// 波特率为 115200
        /// </summary>
        SerialPort devPort = new SerialPort();
        string devPortName = "";

        string keyDirName = "QRCodeTool";
        /// <summary>
        /// 注册列表控制类
        /// </summary>
        CRegEditCtl regEditCtl = null;

        string lastIccId = "";

        const int READ_AT = 0;
        const int READ_AT_ACK = 1;
        /*const int READ_WID = 2;
        const int READ_WID_ACK = 3;
        const int READ_ICCID = 4;
        const int READ_ICCID_ACK = 5;
        const int READ_IMEI = 6;
        const int READ_IMEI_ACK = 7;*/
        const int READ_SIMCARD = 2;
        const int READ_SIMCARD_ACK = 3;
        const int PRINT_QRCODE = 4;
        const int SCAN_QRCODE = 5;//扫码确认
        
        /// <summary>
        /// 读取设备的执行状态
        /// </summary>
        int execStatus = READ_AT;
        /// <summary>
        /// 系统的使用端口索引
        /// </summary>
        int usePortIndex = 0;
        /// <summary>
        /// 扫码结束标志
        /// </summary>
        bool scanQrcodeEnd = false;

        public FrmMain()
        {
            InitializeComponent();
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            string[] portNames = SerialPort.GetPortNames();
            cmbPortName.Items.Clear();
            foreach (string portName in portNames)
            {
                cmbPortName.Items.Add(portName);
            }
            cmbPortName.SelectedIndex = -1;  

            //查看以前保存的打印机串口号为多少
            regEditCtl = new CRegEditCtl();
            object obj = regEditCtl.ReadRegedit(keyDirName, printPortNameKey);
            if (obj != null)
            {
                printPortName = obj.ToString();
                for (int i = 0; i < portNames.Length; i++) {
                    if (!printPortName.Equals(portNames[i]))
                        continue;
                    cmbPortName.SelectedIndex = i;
                    //btnPrintTest_Click(null,null);//启动时，进行打印测试
                    break;
                }
            } else
            {
                regEditCtl.CreateKey(keyDirName);
            }

            //启动读线程
            startReadDevThread();
            /*string name = GetCultureType();*/
            SwitchToLanguageMode("en-US");

            //设置控制焦点
            setControllerFocus();
            this.TopMost = true;//窗体最前
        }

        private void showMassage(string msg) {
            this.Invoke(new EventHandler(delegate { 
                this.TopMost=false;
                FrmMessage frmMessage = new FrmMessage(msg);
                frmMessage.ShowDialog();
                this.TopMost=true;
            }));
        }

        /// <summary>
        /// 设置控制焦点
        /// </summary>
        private void setControllerFocus() { 
            this.Invoke(new EventHandler(delegate {
                this.ActiveControl = this.tbQrcode;
            }));
        }


        /// <summary>
        /// 切换输入法
        /// </summary>
        /// <param name="cultureType">语言项，如zh-CN，en-US</param>
        private static void SwitchToLanguageMode(string cultureType)
        {
            var installedInputLanguages = InputLanguage.InstalledInputLanguages;

            if (installedInputLanguages.Cast<InputLanguage>().Any(i => i.Culture.Name == cultureType))
            {
                InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(System.Globalization.CultureInfo.GetCultureInfo(cultureType));
                //CurrentLanguage = cultureType;
            }
        }


        /// <summary>
        /// 获取当前输入法
        /// </summary>
        /// <returns></returns>
        private static string GetCultureType()
        {
            var currentInputLanguage = InputLanguage.CurrentInputLanguage;
            var cultureInfo = currentInputLanguage.Culture;
            //同 cultureInfo.IetfLanguageTag;
            return cultureInfo.Name;
        }

        private void startReadDevThread() {
            if (printPortName == null || printPortName.Equals("")) {
                showMassage("请先进行打印测试");
                return;
            }
            if (readDevThread != null)
                return;
            readDevRun = true;
            readDevThread = new Thread(readDevAndReceThread);
            readDevThread.IsBackground = true;
            readDevThread.Start();
        }

        private void initDevPort(string devPortName) { 
            if(devPort.IsOpen)
            { 
                devPort.Close(); 
            }

            devPort.PortName = devPortName;
            devPort.BaudRate = 115200;
            devPort.Parity = (Parity)Enum.Parse(typeof(Parity), "None");
            devPort.DataBits = 8;
            devPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), "One");
            devPort.ReadBufferSize = 100;
            devPort.WriteBufferSize = 2048;
            devPort.ReadTimeout = 100;
            devPort.WriteTimeout = 10000;

        }

        private void closeDevPort() { 
            if(devPort.IsOpen)
            { devPort.Close(); }
        }

        private bool sendDevCmd(string devCmd)
        {
            if (devPort == null)
                return false;
            if(!devPort.IsOpen)
            {
                devPort.Open();
            }
            devPort.Write(devCmd);
            return true;
        }

        private string receDevCmd() { 
            if(devPort == null) return ""; 
            if(!devPort.IsOpen)
            {
                return "";
            }
            int timeout = 0;
            const int timeoutCnt = 30;
            do { 
                Thread.Sleep(10);
                timeout++;
            }while (devPort.BytesToRead <= 0 && timeout < timeoutCnt);//在300ms内
            if(devPort.BytesToRead == 0 && timeout >= timeoutCnt) {
                return "";//超时退出
            }
            Thread.Sleep(50);
            int byteRead = devPort.BytesToRead;
            byte[] bytes = new byte[byteRead];
            devPort.Read(bytes, 0, bytes.Length);   
            string cmd = Encoding.ASCII.GetString(bytes);
            return cmd; 
        }

        private void stopReadDevThread() {
            if (readDevThread == null)
                return;
            readDevRun = false;
            readDevThread.Abort();
            readDevThread = null;
        }

        private void printfLog(string log) {
            Console.WriteLine(log);
        }

        private void readDevAndReceThread() {
            //printfLog("readDevAndReceThread start \r\n");
            string usePortName = "";
            int scanTimeoutCnt = 0;//扫描超时次数
            while (readDevRun) {

                //printfLog("readDevAndReceThread run \r\n");

                try { 
                    //获取系统的所有串口名称
                    string[] portNames = SerialPort.GetPortNames();
                    if (portNames.Length <= 1) {
                        usePortIndex = 0;
                        execStatus = READ_AT;
                        Thread.Sleep(10);
                        continue;
                    }
                    usePortName = portNames[usePortIndex];
                    switch(execStatus)
                    {
                        case READ_AT: {
                                //printfLog("READ_AT\r\n");
                                if (usePortName.Equals(printPortName)) { 
                                    usePortIndex++;
                                }
                                if (usePortIndex >= portNames.Length) { 
                                    usePortIndex = 0;
                                    Thread.Sleep(100);
                                    continue;
                                }
                                usePortName = portNames[usePortIndex];
                                initDevPort(usePortName);
                                sendDevCmd("AT\r\n");
                                execStatus = READ_AT_ACK;
                            }break;
                        case READ_AT_ACK: {
                                //printfLog("READ_AT_ACK\r\n");
                                string cmd = receDevCmd();
                                if (cmd.Equals("OK\r\n")) {
                                    execStatus = READ_SIMCARD;
                                } else {
                                    execStatus = READ_AT;
                                }
                            }break;
                        //+SIMCARD:<time>,<res>.< rssi >,< iccid >,< imei >
                        case READ_SIMCARD: {
                                this.Invoke(new EventHandler(delegate {
                                    tbQrcode.Text = "";
                                    scanQrcodeEnd = false;
                                    tbIMEIText.Text = "";
                                    tbICCIDText.Text = "";
                                }));
                                scanTimeoutCnt = 0;
                                printfLog("READ_SIMCARD\r\n");
                                sendDevCmd("AT+SIMCARD=?\r\n");
                                execStatus = READ_SIMCARD_ACK;
                            }
                            break;
                        case READ_SIMCARD_ACK: {
                                printfLog("READ_SIMCARD_ACK\r\n");
                                string cmd = receDevCmd();
                                printfLog("cmd->" + cmd + "\r\n");
                                if (cmd.Contains("SIMCARD")) {
                                    string[] strs = cmd.Split('\r');
                                    string[] strs1 = strs[0].Split(':');
                                    string[] simCardInfo = strs1[1].Split(',');

                                    if (simCardInfo.Length < 5) {
                                        this.Invoke(new EventHandler(delegate {
                                            showMassage("没读到IMEI码，请换设备");
                                        }));
                                        execStatus = READ_SIMCARD;
                                        continue;
                                    }
                                    string iccid = simCardInfo[3];
                                    string imei = simCardInfo[4];
                                    if (iccid.Equals("")) {
                                        this.Invoke(new EventHandler(delegate {
                                            showMassage("iccid码信息为空，请换设备");
                                        }));
                                        execStatus = READ_SIMCARD;
                                        continue;
                                    }

                                    if (imei.Equals("")) {
                                        this.Invoke(new EventHandler(delegate {
                                            showMassage("imei码信息为空，请换设备");
                                        }));
                                        execStatus = READ_SIMCARD;
                                        continue;
                                    }

                                    if (lastIccId.Equals(iccid)) {
                                        execStatus = READ_SIMCARD;
                                        continue;
                                    }

                                    lastIccId = iccid;

                                    this.Invoke(new EventHandler(delegate {
                                        tbICCIDText.Text += iccid;
                                        tbIMEIText.Text += imei;
                                    }));
                                    execStatus = PRINT_QRCODE;
                                } else {
                                    
                                    if(devPort.IsOpen)
                                        devPort.Close();
                                    Thread.Sleep(500);
                                    /*this.Invoke(new EventHandler(delegate {
                                        MessageBox.Show("当前设备不支持条码指令，请更换设备!");
                                    }));*/
                                    execStatus = READ_SIMCARD;
                                }
                            }break;
                        case PRINT_QRCODE: {
                                //printfLog("PRINT_QRCODE start \r\n");
                                if (devPort.IsOpen) { 
                                    devPort.Close();    
                                }
                                this.Invoke(new EventHandler(delegate {
                                    btnRePrint_Click(null,null);
                                }));
                                
                                //printfLog("PRINT_QRCODE end \r\n");
                                execStatus = SCAN_QRCODE;  
                            }break;

                        case SCAN_QRCODE: { //扫码确认
                                //printfLog("SCAN_QRCODE\r\n");
                                string qrCodeInfo = null;
                                if (scanQrcodeEnd == false) {
                                    //printfLog("wait scan qrcode\r\n");
                                    continue;
                                }

                                this.Invoke(new EventHandler(delegate {
                                    qrCodeInfo = tbQrcode.Text.Trim();
                                }));
                                if (qrCodeInfo == null || qrCodeInfo.Equals(""))
                                    continue;
                                string[] strs = qrCodeInfo.Split(new char[] { ',' });
                                string[] imeiStrs = strs[0].Split(new char[] { ':' });
                                string[] iccidStrs = strs[1].Split(new char[] { ':' });
                                string newIccid = iccidStrs[1];
                                string newImei = imeiStrs[1];
                                string oldIccid = tbICCIDText.Text.Trim();
                                string oldImei = tbIMEIText.Text.Trim();
                                if (oldIccid.Equals(newIccid) && oldImei.Equals(newImei)) {
                                    this.Invoke(new EventHandler(delegate {
                                        showMassage("二维码校码完成，请更换下一台设备");
                                    }));
                                    execStatus = READ_SIMCARD;
                                } else {
                                    scanTimeoutCnt++;
                                    if (scanTimeoutCnt < 3) {
                                        this.Invoke(new EventHandler(delegate {
                                            showMassage("请重新扫码");
                                            tbQrcode.Text = string.Empty;
                                            scanQrcodeEnd = false;
                                        }));
                                    } else {
                                        this.Invoke(new EventHandler(delegate {
                                            showMassage("三次确认均不正确，请更换设备");
                                            tbQrcode.Text = string.Empty;
                                            scanQrcodeEnd = false;
                                        }));
                                        execStatus = READ_SIMCARD;
                                    }
                                }
                            }
                            break;
                    }
                }
                catch
                {
                    execStatus = READ_AT;
                }
            }
        }

        private void btnPrintTest_Click(object sender, EventArgs e)
        {
            printPortName = cmbPortName.Text;
            regEditCtl.WriteRegedit(keyDirName,printPortNameKey, printPortName);
            printTest(printPortName);
            setControllerFocus();
        }

        private void printTest(string ppName) {

            if(printPort.IsOpen)
            {
                printPort.Close();
            }
            printPort.PortName = ppName;
            printPort.BaudRate = 9600;
            printPort.Parity = (Parity)Enum.Parse(typeof(Parity), "None");
            printPort.DataBits = 8;
            printPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), "One");
            printPort.ReadBufferSize = 100;
            printPort.WriteBufferSize = 2048;
            printPort.ReadTimeout = 100;
            printPort.WriteTimeout = 10000;

            printPort.Open();

            printPort.Write("SIZE 40 mm,25 mm\r\n");//标签尺寸
            printPort.Write("GAP 2 mm,0 mm\r\n");//间距为0
            printPort.Write("CLS\r\n");
            printPort.Write("DENSITY 7\r\n");
            printPort.Write("REFERENCE 0,0\r\n");
            //printPort.Write("QRCODE 20,20,L,10,A,0,\"www.gainscha.com\"\r\n");
            printPort.Write("TEXT 20,20,\"1\",0,2,2,\"ABCDEFGABCDEFG\"\r\n");
            printPort.Write("TEXT 20,68,\"1\",0,3,3,\"ABCDEFGABCDEFG\"\r\n");
            printPort.Write("TEXT 20,128,\"1\",0,4,4,\"123456789\"\r\n");
            printPort.Write("TEXT 20,190,\"1\",0,5,5,\"123456789\"\r\n");
            printPort.Write("PRINT 1\r\n");

            Thread.Sleep(100);
            printPort.Close();

        }

        private void printQrcode(string qrcode)
        {
            if(printPort.IsOpen)
            { 
                printPort.Close(); 
            }
            printPort.PortName = printPortName;
            printPort.Open();

            printPort.Write("SIZE 40 mm,25 mm\r\n");//标签尺寸
            printPort.Write("GAP 2 mm,0 mm\r\n");//间距为0
            printPort.Write("CLS\r\n");
            printPort.Write("DENSITY 7\r\n");
            printPort.Write("REFERENCE 0,0\r\n");
            printPort.Write("QRCODE 120,20,L,9,A,0,\"" + qrcode + "\"\r\n");
            printPort.Write("TEXT 30,230,\"1\",0,2,3,\"" + qrcode + "\"\r\n");
            printPort.Write("PRINT 1\r\n");

            Thread.Sleep(100);
            printPort.Close();
        }

        private void printSimCardInfo(string iccid, string imei) {
            if (printPort.IsOpen)
            {
                printPort.Close();
            }
            printPort.PortName = printPortName;
            printPort.Open();
            //格式等待客户确认
            printPort.Write("SIZE 40 mm,25 mm\r\n");//标签尺寸
            printPort.Write("GAP 2 mm,0 mm\r\n");//间距为2 mm
            printPort.Write("CLS\r\n");
            printPort.Write("DENSITY 7\r\n");
            printPort.Write("REFERENCE 0,0\r\n");
            printPort.Write("QRCODE 130,8,L,7,M,0,\"IMEI:" + imei + ",ICCID:" + iccid + "\"\r\n");
            printPort.Write("TEXT 120,225,\"1\",0,1,2,\"IMEI:" + imei + "\"\r\n");
            printPort.Write("TEXT 120,252,\"1\",0,1,2,\"ICCID:" + iccid + "\"\r\n");
            printPort.Write("PRINT 1\r\n");

            Thread.Sleep(100);
            printPort.Close();
        }

        private void btnRePrint_Click(object sender, EventArgs e)
        {
            string imei = tbIMEIText.Text.Trim();
            string iccid = tbICCIDText.Text.Trim();
            //printQrcode(qrcode);
            //printSimCardInfo("89860622350011298310", "865328062435994");
            printSimCardInfo(iccid, imei);

            setControllerFocus();
        }

        private void btnFindDevPort_Click(object sender, EventArgs e)
        {
            usePortIndex = 0;
            execStatus = READ_AT;
            setControllerFocus();
        }

        private void tbQrcode_KeyDown(object sender, KeyEventArgs e)
        {   
            if(timer.Enabled)
                timer.Enabled = false;  

            timer.Interval = 150;
            timer.Enabled = true;
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            timer.Enabled=false;
            
            string qrcodeInfo = tbQrcode.Text.Trim();
            if (qrcodeInfo.Equals(""))
                return;

            scanQrcodeEnd = true;//扫码结束
        }
    }
}
